﻿#include <stdio.h>
#include <string.h>
#include <stdlib.h>
#include <time.h>

#define SNAKE_MAX_LEN 20
#define SNAKE_HEAD 'H'
#define SNAKE_BODY 'X'
#define BLANK_CELL ' '
#define SNAKE_FOOD '$'
#define WALL_CELL '*'

// 移动蛇：dx, dy
void snake_move(int, int);

// 结束游戏
void game_over(void);

// 输出字符矩阵
void print_map(void);

// 生成食物
void generate_food(void);

// 游戏结束
int gameOver = 0;

// 蛇的长度
int snakeLength = 5;

// 蛇身体的行坐标
int snakeX[SNAKE_MAX_LEN] = { 1,1,1,1,1 };

// 蛇身体的列坐标
int snakeY[SNAKE_MAX_LEN] = { 1,2,3,4,5 };

// 食物的行列坐标
int foodX = 0, foodY = 0;

// 空地图
char map[12][12] = {
	"************",
	"*          *",
	"*          *",
	"*          *",
	"*          *",
	"*          *",
	"*          *",
	"*          *",
	"*          *",
	"*          *",
	"*          *",
	"************"
};

int main(void) {
	srand((unsigned int)time(NULL));
	char input;
	generate_food();
	print_map();
	while (!gameOver) {
		input = getchar();
		switch (input) {
		case 'A': // 向左移动
			snake_move(0, -1);
			break;
		case 'D': // 向右移动
			snake_move(0, 1);
			break;
		case 'W': // 向上移动
			snake_move(-1, 0);
			break;
		case 'S': // 向下移动
			snake_move(1, 0);
			break;
		default:
			continue;
		}
		print_map();
	}
	printf("Game Over!!\n");
	return 0;
}

void game_over(void) {
	gameOver = 1;
}

void snake_move(int dx, int dy) {
	// 计算蛇头的新位置
	int i, x = snakeX[snakeLength - 1] + dx, y = snakeY[snakeLength - 1] + dy;

	// 判断是否吃到食物
	if (x == foodX && y == foodY) {
		// 若蛇超过最长长度则游戏结束
		if (snakeLength + 1 == SNAKE_MAX_LEN) {
			game_over();
			return;
		}
		snakeX[snakeLength] = x;
		snakeY[snakeLength] = y;
		snakeLength++;
		generate_food();
		return;
	}

	// 判断是否撞到墙壁
	if (x > 10 || x < 1 || y > 10 || y < 1) {
		game_over();
		return;
	}

	// 判断是否撞到自身
	for (i = 1; i < snakeLength; i++) {
		if (snakeX[i] == x && snakeY[i] == y) {
			game_over();
			return;
		}
	}

	// 更新蛇的位置
	for (i = 0; i < snakeLength - 1; i++) {
		snakeX[i] = snakeX[i + 1];
		snakeY[i] = snakeY[i + 1];
	}
	snakeX[snakeLength - 1] = x;
	snakeY[snakeLength - 1] = y;
}

void print_map(void) {
	int i, j, k;
	char ch;
	for (i = 0; i < 12; i++) {
		for (j = 0; j < 12; j++) {
			ch = map[i][j];
			for (k = 0; k < snakeLength; k++) {
				if (snakeX[k] == i && snakeY[k] == j) {
					ch = k == snakeLength - 1 ? SNAKE_HEAD : SNAKE_BODY;
				}
				if (i == foodX && j == foodY) {
					ch = SNAKE_FOOD;
				}
			}
			printf("%c", ch);
		}
		printf("\n");
	}
	printf("----------------------\n");
}

void generate_food(void) {
	int isSnakeBody, i;
	do {
		isSnakeBody = 0;
		foodX = rand() % 10 + 1;
		foodY = rand() % 10 + 1;
		for (i = 0; i < snakeLength; i++) {
			if (snakeX[i] == foodX && snakeY[i] == foodY) {
				isSnakeBody = 1;
				break;
			}
		}
	} while (isSnakeBody);
}
